package com.oneplus.network.core;


import com.oneplus.constants.Constants;
import com.oneplus.encryption.ECKey;
import com.oneplus.encryption.SHAEncrypt;
import com.oneplus.entitys.Block;
import com.oneplus.entitys.BlockHead;
import com.oneplus.entitys.Transaction;
import com.oneplus.entitys.TransactionHead;
import com.oneplus.repositorys.BlockRepository;
import com.oneplus.repositorys.NodeAddressRepository;
import com.oneplus.repositorys.TransactionRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongycastle.util.encoders.Hex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;


@Component
public class GenesisBlock {
    final static Logger logger = LoggerFactory.getLogger(GenesisBlock.class);


    @Autowired
    private BlockRepository blockRepository;
    @Autowired
    private TransactionRepository transactionRepository;
    @Autowired
    private NodeAddressRepository nodeAddressRepository;

    public static final long GENESIS_TIME = Constants.GENESIS_TIME;
    public static final long RECEIVE_QUANTITY = 43000000L * Constants.MININUMUNIT;
    private static final byte[] GENESIS_PUBLIC_KEY = {4,-63,97,0,40,103,-96,-121,48,14,-126,-13,-31,-92,-114,125,101,43,-115,79,117,66,-121,58,-27,-72,-17,-112,-106,53,-79,46,-65,-66,-119,116,45,12,-15,45,6,35,-101,44,-4,43,90,99,31,-104,19,-39,-43,-125,109,39,15,33,111,-60,86,70,99,-41,55};
    private static final byte[] ACCEPTER = {4,-107,-92,84,75,-67,-125,-30,-67,110,-72,-31,36,61,-25,-56,20,26,-44,59,-58,-16,115,-27,-82,-3,-107,-59,20,75,-28,-7,-6,-25,120,53,51,39,-103,88,-63,-74,-39,106,-118,121,21,-112,-124,80,-81,78,18,43,26,116,27,-38,-107,98,-98,-108,-80,16,-50};
    private static final String HASH_PREV_BLOCK = "aced000570";
    private static final String TRANS_SIGNATURE = "7b2272223a35313434363238373235303732343438333130323832333537323536383231323238323732363339353535383838343633313938383032323435393531323031353031313331393535393439322c2273223a31393434353233333538363638363930333333363837363935363836343735313332383138343431363439373436373130363737303332363539363736373031303635393736343135323531312c2276223a32377d";
    private static final String HASH_MERKLE_ROOT = "31633863333265636363306662633635366262393132333062336166343062313465643265346137653435303831643063313939653366396234383933376337";
    private static final String BLOCK_SIGNATURE = "7b2272223a37393233323337363336313438393130323337383338393331373434323338323436313030343533343431333534383135313938393638373630363836313738343030303732373235323337352c2273223a31393436373832313435343331323831333830383635353138383934393639363030303334323739393234333931313036323936373435303733343735373839353339353233353639353539362c2276223a32377d";

    @Transactional(rollbackFor = Exception.class)
    public void init() {
        if (blockRepository.count() == 0) {
            logger.info("MainAccount:" + ECKey.pubkeyToAddress(Hex.toHexString(ACCEPTER)));
            TransactionHead transactionHead = new TransactionHead(Hex.toHexString(GENESIS_PUBLIC_KEY), Hex.toHexString(ACCEPTER), RECEIVE_QUANTITY, 0, GENESIS_TIME);
            BlockHead blockHead = new BlockHead(Constants.BLOCK_VERSION, GENESIS_TIME, Constants.CUMULATIVE_DIFFICULTY, Hex.decode(HASH_PREV_BLOCK), Hex.decode(HASH_MERKLE_ROOT));
            Transaction transaction = new Transaction(Hex.decode(TRANS_SIGNATURE), transactionHead, 0, 0, Hex.toHexString(GENESIS_PUBLIC_KEY), Hex.toHexString(ACCEPTER), "", Constants.MAIN_COIN, 1, RECEIVE_QUANTITY, 0);
            List<Transaction> transactionList = new ArrayList<>();
            transactionList.add(transaction);
            Block block = new Block(0, 425, RECEIVE_QUANTITY, 0, Hex.decode(BLOCK_SIGNATURE), GENESIS_PUBLIC_KEY, blockHead, transactionList);
            block.setBlockHash(Hex.toHexString(SHAEncrypt.SHA256(blockHead)));
            System.out.println(block.getBlockHash());
            transactionRepository.save(transaction);
            blockRepository.save(block);
        }
    }
}
